package com.cdhkppm.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.alibaba.fastjson.JSONObject;
import com.hustcad.plm.pdm.core.handle.exception.SystemErrorCodeEnum;
import com.hustcad.plm.rpm.util.beanmapper.BeanMapper;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.time.LocalDateTime;
import java.util.*;

/**
 * @author yfq
 * @apiNote
 */
public class CustomExcelUtils {
    public static <T> Workbook listToExcelWithOutIndex(List<T> result, Map<String, String> fieldMap) {
        Workbook workbook = createWorkBookByModel("XSSFWorkbook");
        Sheet sheet = workbook.createSheet();
        if (CollUtil.isEmpty(result)) {
            return workbook;
        } else if (CollUtil.isEmpty(fieldMap)) {
            throw SystemErrorCodeEnum.EXCEL_FIELD_MAP_EMPTY.message();
        } else {
            CellStyle titleCellStylel = initTitleCellStyle(workbook);
            List<String> display = new ArrayList(fieldMap.values());
            Row startRow = sheet.createRow(0);

            for(int i = 0; i < display.size(); ++i) {
                Cell cell = startRow.createCell(i);
                cell.setCellValue((String)display.get(i));
                cell.setCellStyle(titleCellStylel);
            }

            List<JSONObject> tempList = BeanMapper.mapAsList(result, JSONObject.class);
            List<String> keyList = new ArrayList(fieldMap.keySet());
            int rowIndex = 1;
            List<CellStyle> cellStyleList = new ArrayList();
            CellStyle cellStyleLeft = initCommonCellStyle(workbook);
            cellStyleLeft.setAlignment(HorizontalAlignment.LEFT);
            cellStyleList.add(cellStyleLeft);
            CellStyle cellStyleCenter = initCommonCellStyle(workbook);
            cellStyleList.add(cellStyleCenter);
            CellStyle cellStyleRight = initCommonCellStyle(workbook);
            cellStyleRight.setAlignment(HorizontalAlignment.RIGHT);
            cellStyleList.add(cellStyleRight);
            CellStyle cellStyleDate = initCommonDateCellStyle(workbook);
            cellStyleList.add(cellStyleDate);
            List<Integer> columnWidthList = new ArrayList();

            for(Iterator var16 = tempList.iterator(); var16.hasNext(); ++rowIndex) {
                JSONObject object = (JSONObject)var16.next();
                Row tempRow = sheet.createRow(rowIndex);

                for(int j = 0; j < keyList.size(); ++j) {
                    String tempKey = (String)keyList.get(j);
                    Cell cell = tempRow.createCell(j);
                    setCellValueByField(cell, cellStyleList, object, tempKey, columnWidthList, j);
                }
            }

            return workbook;
        }
    }

    private static CellStyle initCommonDateCellStyle(Workbook workbook) {
        CellStyle cellStyle = initCommonCellStyle(workbook);
        cellStyle.setDataFormat((short)14);
        return cellStyle;
    }


    private static CellStyle initTitleCellStyle(Workbook workbook) {
        CellStyle titleStyle = workbook.createCellStyle();
        titleStyle.setBorderBottom(BorderStyle.THIN);
        titleStyle.setBorderLeft(BorderStyle.THIN);
        titleStyle.setBorderRight(BorderStyle.THIN);
        titleStyle.setBorderTop(BorderStyle.THIN);
        Font titleFont = workbook.createFont();
        titleFont.setBold(true);
        titleStyle.setFont(titleFont);
        titleStyle.setAlignment(HorizontalAlignment.CENTER);
        titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        return titleStyle;
    }

    private static CellStyle initCommonCellStyle(Workbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        return cellStyle;
    }

    public static Workbook createWorkBookByModel(String model) {
        switch (model) {
            case "HSSFWorkbook":
                return new HSSFWorkbook();
            case "XSSFWorkbook":
                return new XSSFWorkbook();
            case "SXSSFWorkbook":
                return new SXSSFWorkbook();
            default:
                throw SystemErrorCodeEnum.NOT_SUPPORT_FILE_TYPE.message(new Object[0]);
        }
    }
    private static String booleanToChinese(boolean booleanValue) {
        return Boolean.TRUE.equals(booleanValue) ? "是" : "";
    }

    private static void setCellValueByField(Cell cell, List<CellStyle> cellStyleList, JSONObject object, String key, List<Integer> columnWidthList, int index) {
        Object o = object.get(key);
        CellStyle tempStyle = (CellStyle)cellStyleList.get(1);
        if (!Objects.isNull(o) && !CharSequenceUtil.equals("null", String.valueOf(o))) {
            switch (o.getClass().getSimpleName()) {
                case "Boolean":
                    String boolChinese = booleanToChinese(object.getBooleanValue(key));
                    cell.setCellValue(boolChinese);
                    setColumnWidth(columnWidthList, index, boolChinese);
                    break;
                case "Integer":
                    cell.setCellValue((double)object.getInteger(key));
                    tempStyle = (CellStyle)cellStyleList.get(2);
                    setColumnWidth(columnWidthList, index, "");
                    break;
                case "Float":
                    cell.setCellValue((double)object.getFloat(key));
                    tempStyle = (CellStyle)cellStyleList.get(2);
                    setColumnWidth(columnWidthList, index, "");
                    break;
                case "Date":
                    Date date = object.getDate(key);
                    cell.setCellValue(date);
                    tempStyle = (CellStyle)cellStyleList.get(3);
                    setColumnWidth(columnWidthList, index, date.toString());
                    break;
                case "LocalDateTime":
                    LocalDateTime localDateTime = (LocalDateTime)o;
                    cell.setCellValue(localDateTime.toLocalDate());
                    tempStyle = (CellStyle)cellStyleList.get(3);
                    setColumnWidth(columnWidthList, index, localDateTime.toString());
                    break;
                case "String":
                default:
                    String str = object.getString(key);
                    cell.setCellValue(str);
                    tempStyle = (CellStyle)cellStyleList.get(0);
                    setColumnWidth(columnWidthList, index, str);
            }

            cell.setCellStyle(tempStyle);
        } else {
            cell.setCellStyle(tempStyle);
        }
    }

    private static void setColumnWidth(List<Integer> columnWidthList, int j, String cellValue) {
        Integer oriWidth = 0;
        int size = columnWidthList.size();
        int length;
        if (size > j) {
            oriWidth = (Integer)columnWidthList.get(j);
        } else {
            for(length = size; length <= j; ++length) {
                columnWidthList.add(0);
            }
        }

        length = cellValue.getBytes().length;
        if (oriWidth < length) {
            columnWidthList.set(j, length);
        }

    }
}
